package com.pkk.penguin.frame.know.springmvc.controller;

import com.pkk.penguin.frame.know.springmvc.entity.Dept;
import com.pkk.penguin.frame.know.springmvc.entity.User;
import java.util.Arrays;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.CookieValue;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.SessionAttributes;
import org.springframework.web.servlet.ModelAndView;

/**
 * Created by peikunkun on 2017/12/30 0030.
 */
@Controller
@RequestMapping(value = "modelAttribute")
/*将Model中的属性名为user,和dept属性存放在HttpSession中*/
@SessionAttributes(types = {User.class, Dept.class}, value = {"user", "dept"})
public class ModelAttributeController {

  /*用此@ModelAttribute注解标注之后,当我们调用login的方法的时候，会首先调用userModel方法，我们把user对象放进Model或ModelMap中之后，会自动传递到login中，获取user对象*/
  @ModelAttribute
  public void userModel(String username, String password, Model model, ModelAndView modelAndView) {
    System.out.println("进入@ModelAttribute标记的方法");
    User user = new User();
    user.setUsername(username);
    user.setPassword(password);
    model.addAttribute("user", user);
    modelAndView.addObject("user", user);

  }

  /*请求地址为login，设置请求方法为post或get的才会调用此方法*/
  @RequestMapping(value = "/login", method = {RequestMethod.GET, RequestMethod.POST})
  public String login(Model model) {
    User user = (User) model.asMap().get("user");
    System.out.println("获取的User对象:" + user);
    return "modelAttribute";
  }

  /*请求地址为login1，设置请求方法为post或get的才会调用此方法*/
  @RequestMapping(value = "/login1", method = {RequestMethod.GET, RequestMethod.POST})
  public ModelAndView login(ModelAndView modelAndView) {
    /*获取模型数据*/
    User user = (User) modelAndView.getModel().get("user");
    modelAndView.addObject("user", user);
    System.out.println("获取的User对象:" + user);
    /*设置要跳转的视图*/
    modelAndView.setViewName("modelAttribute1");
    return modelAndView;
  }


  /*请求地址为login2，设置请求方法为post或get的才会调用此方法*/
  @RequestMapping(value = "/login2", method = {RequestMethod.GET, RequestMethod.POST})
  /*使用@RequestParam注解绑定前台传递的参数username和password,并且通过required=false设置为password为不必传，设置默认不传的时候密码为defaultpassword*/
  /*例如请求的是http://localhost:8080/modelAttribute/login2.action?username="123"则会通过@RequestParam的value值为username的进行映射给String的userName*/
  /*但是如果我们传了requried=true的但是为空，这是不报错的，知识有此参数没有值而已*/
  public String login(@RequestParam(value = "username", required = true) String userName,
      @RequestParam(value = "password", required = false, defaultValue = "defaultpassword") String passWord) {
    System.out.println("获取的用户名为：" + userName + "密码为:" + passWord);
    return "modelAttribute2";
  }


  @RequestMapping(value = "/pathVariableTest/{userId}")
    /*如果@Pathvariable注解使用了默认的value则在绑定参数的时候，会默认绑定同名的参数userId身上，
    如果找不到，则无法映射绑定参数,报异常[com.com.pkk.penguin.frame.know.springmvc.controller.ModelAttributeController.pathVariableTest(java.lang.Integer,org.springframework.ui.Model)]; nested exception is java.lang.IllegalStateException: Could not find @PathVariable [userId] in @RequestMapping]*/
  public String pathVariableTest(@PathVariable Integer userId, Model model) {
    System.out.println("获取的用户id为：" + userId);
    model.addAttribute("message", "获取的用户id为：" + userId);
    return "modelAttribute3";
  }

  @RequestMapping(value = "/requestHeaderTest")
  /*所请求的头文件必须包含Accept,因为requried默认为truem否则报错，或设置requried为false，之后获取的Accept会主动映射到accepts数组中去*/
  public String requestHeaderTest(@RequestHeader(value = "Accept") String[] accepts, Model model) {
    System.out.println("获取的用户请求头accepts信息为：" + Arrays.toString(accepts));
    model.addAttribute("message", "获取的用户请求头accepts信息为：" + Arrays.toString(accepts));
    return "modelAttribute4";
  }

  @RequestMapping(value = "/cookieValueTest")
  /*所获取cooki必须包含JSESSIONID,因为requried默认为truem否则报错，或设置requried为false，之后获取的Accept会主动映射到accepts数组中去*/
  public String cookieValueTest(@CookieValue(value = "JSESSIONID", defaultValue = "") String sessionId, Model model) {
    System.out.println("获取的cookie的session信息为：" + sessionId);
    model.addAttribute("message", "获取的cookie的session信息为：" + sessionId);
    return "modelAttribute5";
  }


  @RequestMapping(value = "/sessionAttributesTest")
  /*获取前台传递的username，和deptname，使用required = false设置为并非含有此字段，分别赋值给userName和deptName*/
  public String sessionAttributesTest(@RequestParam(value = "username", required = false) String userName,
      @RequestParam(value = "deptname", required = false) String deptName, Model model) {
    System.out.println("使用@sessionAttributes将参数设置到session中");

    User user = new User();
    user.setUsername(userName);

    Dept dept = new Dept();
    dept.setDeptname(deptName);

    model.addAttribute("user", user);
    model.addAttribute("dept", dept);
    return "modelAttribute6";
  }


  /*---------------ModelAttribute的使用方式   Begin---------------*/

  @ModelAttribute(value = "username")
  /*首先ModelAttribute会先于请求方法调用，请求的username会寻找到(@RequestParam(value = "username")，然后username匹配，之后把username映射到userName中，同时自动把username添加到Model中去
   * 注意，这里存入Model中的属性值为username，并不是后面起的参数属性值：userName,*/
  public String modelAttributeTest1(@RequestParam(value = "username") String userName) {
    System.out.println("modelAttributeTest中的username为(返回值为一个类String):" + userName);
    return userName;
  }


  @ModelAttribute(value = "username")
    /*首先ModelAttribute会先于请求方法调用，请求的username会寻找到(@RequestParam(value = "username")，然后username匹配，之后把username映射到userName中，
    同时手动把username添加到Model中去*/
  public void modelAttributeTest2(@RequestParam(value = "username") String userName, Model model) {
    System.out.println("modelAttributeTest中的username为（返回值为void）:" + userName);
    model.addAttribute("username", userName);
  }


  @ModelAttribute(value = "username")
    /*首先ModelAttribute会先于请求方法调用，请求的username会寻找到(@RequestParam(value = "username")，然后username匹配，之后把username映射到userName中，
    同时手动把username添加到Model中去*/
  public User modelAttributeTest3(@RequestParam(value = "username") String userName) {
    System.out.println("modelAttributeTest中的username为（返回值为void）:" + userName);
    User user = new User();
    user.setUsername(userName);
    /*返回的时候，属性默认为实体类首字母小写如User返回的key为user，值为user这个对象*/
    return user;
  }


  /*请求地址为modelAttribute7，设置请求方法为post或get的才会调用此方法*/
  @RequestMapping(value = "modelAttribute7", method = {RequestMethod.GET, RequestMethod.POST})
  @ModelAttribute(value = "username")
    /*首先ModelAttribute会先于请求方法调用，请求的username会寻找到(@RequestParam(value = "username")，然后username匹配，之后把username映射到userName中，
    同时自动把username添加到Model中去*/
  public String modelAttributeTest4(@RequestParam(value = "username") String userName) {
    System.out.println("modelAttributeTest中的username为（返回值为void）:" + userName);
    /*注意还是首先执行的是@ModelAttribute注解，只是相当于两个方法重复了，一样，所以先执行ModelAttribute标志的方法，请求的username参数映射之后返回username的值，也就是相当于request内部封装了username=username[不固定前台传过来的值]，然后再执行RequestMapping的方法进行页面跳转*/
    /*但是值得注意的是，此时跳转的是当前路径的../modelAttribute7.jsp页面而不是返回的userName的页面，这要特此注意*/
    return userName;
  }




  /*---------------ModelAttribute的使用方式   End---------------*/

}
